<template>
	<view class="container" @tap="closeEmojiPicker">
		<!-- 顶部状态栏 -->
		<view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
		
		<!-- 导航栏 -->
		<view class="nav-bar">
			<view class="back-btn" @tap="goBack">
				<text class="back-icon">←</text>
			</view>
			<view class="nav-title">AI 助手</view>
			<view class="action-btn" @tap="showMenu">
				<text class="action-icon">⋮</text>
			</view>
		</view>
		
		<!-- 消息列表 -->
		<scroll-view 
			class="message-list" 
			scroll-y 
			:scroll-top="scrollTop"
			:scroll-with-animation="true"
			@scrolltoupper="onScrollToUpper"
			@scroll="onScroll"
			upper-threshold="100"
			:show-scrollbar="false"
			:enhanced="true"
			:bounces="false"
			:style="{ height: `calc(100vh - ${statusBarHeight + 88 + 120}px)` }"
			:class="{ 'fade-in': messages.length > 0 }"
		>
			<!-- 加载更多提示 -->
			<view class="loading-more" v-if="isLoading">
				<view class="loading-spinner"></view>
				<text>加载更多消息...</text>
			</view>
			
			<!-- 消息内容 -->
			<view class="messages-container">
				<!-- 欢迎消息 -->
				<view class="welcome-message" v-if="messages.length === 0">
					<view class="welcome-header">
						<image class="assistant-avatar" :src="aiAvatar" mode="aspectFill"></image>
						<text class="welcome-title">你好，我是你的 AI 助手</text>
					</view>
					<text class="welcome-text">我可以帮你回答问题、提供建议、讲故事，甚至陪你聊天。试着问我一些问题吧！</text>
					
					<view class="quick-questions">
						<text class="quick-questions-title">你可以问我：</text>
						<view 
							v-for="(question, index) in quickActions" 
							:key="index"
							class="quick-question"
							@tap="sendQuickAction(question)"
						>
							<text>{{ question }}</text>
						</view>
					</view>
				</view>
				
				<!-- 消息列表 -->
				<block v-for="(msg, index) in messages" :key="index">
					<!-- 时间戳消息 -->
					<view class="time-divider" v-if="msg.type === 'timestamp'">
						<text class="time-text">{{ formatTime(msg.time) }}</text>
					</view>
					
					<!-- 系统消息 -->
					<view class="message-item system-message" v-else-if="msg.type === 'system'">
						<view class="system-text">{{ msg.content }}</view>
					</view>
					
					<!-- 普通消息 -->
					<view class="message-item" :class="{ 'fade-in': true }">
						<!-- 用户消息 -->
						<view v-if="msg.type === 'user'" class="message-content user">
							<!-- 消息气泡 -->
							<view class="message-bubble" @longpress="showMessageActions(msg, index)">
								<text class="message-text">{{ msg.content }}</text>
								<image 
									v-if="msg.image" 
									:src="msg.image" 
									class="message-image" 
									mode="widthFix" 
									@tap="previewImage(msg.image)"
								></image>
							</view>
							
							<!-- 用户头像 (右侧) -->
							<view class="message-avatar">
								<image :src="userAvatar" mode="aspectFill"></image>
							</view>
						</view>
						
						<!-- AI消息 -->
						<view v-else class="message-content ai">
							<!-- AI头像 (左侧) -->
							<view class="message-avatar">
								<image :src="aiAvatar" mode="aspectFill"></image>
							</view>
							
							<!-- 消息气泡 -->
							<view class="message-bubble" @longpress="showMessageActions(msg, index)">
								<text class="message-text">{{ msg.content }}</text>
								<image 
									v-if="msg.image" 
									:src="msg.image" 
									class="message-image" 
									mode="widthFix" 
									@tap="previewImage(msg.image)"
								></image>
							</view>
						</view>
					</view>
				</block>
				
				<!-- AI 输入状态 -->
				<view class="typing-indicator" v-if="isAiTyping">
					<view class="message-item">
						<view class="message-content ai">
							<!-- AI头像 (左侧) -->
							<view class="message-avatar">
								<image :src="aiAvatar" mode="aspectFill"></image>
							</view>
							
							<!-- 打字气泡 -->
							<view class="typing-bubble">
								<view class="typing-dot"></view>
								<view class="typing-dot"></view>
								<view class="typing-dot"></view>
							</view>
						</view>
					</view>
				</view>
			</view>
		</scroll-view>
		
		<!-- 底部输入区域 -->
		<view class="input-area">
			<view class="input-wrapper">
				<textarea
					class="message-input"
					v-model="inputMessage"
					placeholder="发送消息给 AI 助手..."
					:auto-height="true"
					:cursor-spacing="20"
					:maxlength="-1"
					:show-confirm-bar="false"
					:adjust-position="false"
					@confirm="sendMessage"
					@focus="onInputFocus"
					@blur="onInputBlur"
					ref="chatInput"
				></textarea>
				
				<view class="send-btn" :class="{ 'active': inputMessage.trim().length > 0 }" @tap="sendMessage">
					<text class="send-icon">↑</text>
				</view>
			</view>
			
			<view class="quick-actions">
				<view class="action-btn voice-btn" @touchstart="startVoice" @touchend="stopVoice">
					<text class="action-icon">🎤</text>
				</view>
				<view class="action-btn image-btn" @tap="uploadImage">
					<text class="action-icon">🖼️</text>
				</view>
				<view class="action-btn emoji-btn" @tap.stop="toggleEmojiPicker">
					<text class="action-icon">😊</text>
				</view>
			</view>
		</view>
		
		<!-- 录音动画 -->
		<view class="voice-recording" v-if="recording">
			<view class="recording-waves">
				<view class="wave wave-1"></view>
				<view class="wave wave-2"></view>
				<view class="wave wave-3"></view>
			</view>
			<text class="recording-text">松开发送，上滑取消</text>
		</view>
		
		<!-- 表情选择器 -->
		<view class="emoji-picker" v-if="showEmojiPicker" @tap.stop>
			<view class="emoji-picker-mask" @tap="closeEmojiPicker"></view>
			<view class="emoji-picker-content">
				<view class="emoji-picker-header">
					<text class="emoji-picker-title">选择表情</text>
					<text class="emoji-picker-close" @tap="closeEmojiPicker">×</text>
				</view>
				<scroll-view scroll-y class="emoji-grid">
					<view 
						v-for="(group, groupName) in emojiGroups" 
						:key="groupName"
						class="emoji-group"
					>
						<text class="group-title">{{ groupName }}</text>
						<view class="emoji-list">
							<view 
								v-for="(emoji, idx) in group" 
								:key="idx"
								class="emoji-item"
								@tap="insertEmoji(emoji)"
							>
								<text>{{ emoji }}</text>
							</view>
						</view>
					</view>
				</scroll-view>
			</view>
		</view>
		
		<!-- API选择弹窗 -->
		<view class="model-picker" v-if="showApiPopup">
			<view class="model-picker-mask" @tap="showApiPopup = false"></view>
			<view class="model-picker-content">
				<view class="model-picker-header">
					<text class="model-picker-title">选择AI模型</text>
					<text class="model-picker-close" @tap="showApiPopup = false">×</text>
				</view>
				<scroll-view class="model-picker-scroll" scroll-y>
					<view 
						v-for="api in availableApis" 
						:key="api.key"
						class="model-picker-item"
						:class="{ 'model-active': currentApi === api.key }"
						@tap="selectApi(api.key)"
					>
						<text class="model-name">{{ api.name }}</text>
						<text class="model-desc">{{ api.description }}</text>
					</view>
				</scroll-view>
			</view>
		</view>
		
		<!-- 菜单弹窗 -->
		<view class="theme-picker" v-if="showMenuPopup">
			<view class="theme-picker-mask" @tap="hideMenu"></view>
			<view class="theme-picker-content">
				<view class="theme-picker-header">
					<text class="theme-picker-title">菜单选项</text>
					<text class="theme-picker-close" @tap="hideMenu">×</text>
				</view>
				<view class="theme-picker-list">
					<view class="theme-picker-item" @tap="showApiSelector">
						<text class="theme-name">切换AI模型</text>
					</view>
					<view class="theme-picker-item" @tap="clearChat">
						<text class="theme-name">清空聊天记录</text>
					</view>
					<view class="theme-picker-item" @tap="openSettings">
						<text class="theme-name">设置</text>
					</view>
				</view>
			</view>
		</view>
		
		<!-- 设置面板 -->
		<view class="settings-backdrop" v-if="showSettings" @tap="hideSettings"></view>
		<view class="settings-panel" v-if="showSettings" :class="{ 'visible': showSettings }" @tap.stop>
			<view class="panel-header">
				<text class="panel-title">设置</text>
				<view class="close-btn" @tap="hideSettings">×</view>
			</view>
			<scroll-view scroll-y class="panel-content">
				<view class="setting-group">
					<text class="group-title">聊天设置</text>
					<view class="setting-item">
						<text>深色模式</text>
						<switch :checked="isDarkMode" @change="toggleDarkMode" />
					</view>
					<view class="setting-item">
						<text>字体大小</text>
						<view class="slider-container">
							<text class="slider-value">{{ fontSize }}px</text>
							<slider 
								:value="fontSize" 
								:min="12" 
								:max="24" 
								:step="1"
								@change="changeFontSize" 
								activeColor="#0091EA"
								blockColor="#2979FF"
								class="font-slider"
								:block-size="24"
							/>
						</view>
					</view>
				</view>
				<view class="setting-group">
					<text class="group-title">AI设置</text>
					<view class="setting-item">
						<text>连续对话</text>
						<switch :checked="enableContext" @change="toggleContext" />
					</view>
					<view class="setting-item">
						<text>自动回复</text>
						<switch :checked="autoReply" @change="toggleAutoReply" />
					</view>
				</view>
			</scroll-view>
		</view>
	</view>
</template>

<script>
import { aiService } from '@/services/ai.js'
import { imageService } from '@/services/image.js'

export default {
	data() {
		return {
			pageSize: 15, // 每页显示的消息数量
			currentPage: 1, // 当前页码
			allMessages: [], // 存储所有消息
			messages: [], // 当前显示的消息
			isLoading: false, // 是否正在加载更多
			hasMore: true, // 是否还有更多消息
			inputMessage: '',
			scrollTop: 0,
			userAvatar: '/static/images/avatar/user.png',
			aiAvatar: '/static/images/avatar/ai.png',
			isAiTyping: false,
			isRefreshing: false,
			showMenuPopup: false,
			showEmojiPicker: false,
			showSettings: false,
			recording: false,
			statusBarHeight: 0,
			isDarkMode: false,
			fontSize: 16,
			enableContext: true,
			autoReply: false,
			quickActions: [
				'你好，请介绍一下你自己',
				'今天天气怎么样？',
				'讲个笑话',
				'写一首诗'
			],
			emojiGroups: {
				'常用': ['😊', '😂', '😍', '🤔', '👍', '👎', '👌', '🙏', '❤️', '🔥', '🎉', '👀', '✨', '⭐', '🌟', '💯'],
				'表情': ['😀', '😃', '😄', '😆', '😋', '😎', '😏', '😒', '😞', '😔', '😢', '😭', '😤', '😠', '😡', '🤮'],
				'动物': ['🐶', '🐱', '🐭', '🐹', '🐰', '🦊', '🐻', '🐼', '🐨', '🐯', '🦁', '🐮', '🐷', '🐸', '🐵', '🐦'],
				'食物': ['🍎', '🍐', '🍊', '🍋', '🍌', '🍉', '🍇', '🍓', '🍈', '🍒', '🍑', '🍍', '🍕', '🍔', '🍟', '🍩']
			},
			inputRef: 'chatInput',
			showApiPopup: false,
			currentApi: 'deepseek-v3',
			availableApis: [],
			currentApiName: 'DeepSeek V3',
			lastScrollTop: 0,
			isScrollingUp: false,
			showImagePreview: false,
			currentImage: '',
			isAutoScrolling: false,
			stream: false,
			temperature: 0.7,
			top_p: 0.9
		}
	},
	async onLoad() {
		// 获取状态栏高度
		this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight
		
		// 默认模型列表
		const defaultModels = [
			{
				key: 'deepseek-v3',
				name: 'DeepSeek V3',
				description: 'DeepSeek最新版本模型'
			},
			{
				key: 'deepseek-r1',
				name: 'DeepSeek R1',
				description: 'DeepSeek基础版本'
			},
			{
				key: 'qwq-32b',
				name: 'QWQ-32B',
				description: '离线大语言模型'
			},
			{
				key: 'qwq-32b-online',
				name: 'QWQ-32B在线版',
				description: '在线大语言模型'
			},
			{
				key: 'qwen-max',
				name: '通义千问Max',
				description: '通义千问最强性能版本'
			},
			{
				key: 'qwen-plus',
				name: '通义千问Plus',
				description: '通义千问增强版本'
			},
			{
				key: 'qwen-turbo',
				name: '通义千问Turbo',
				description: '通义千问快速版本'
				}
			];
			
			// 先设置默认模型列表
			this.availableApis = [...defaultModels];
			
			try {
				// 获取可用的模型列表
				const response = await uni.request({
					url: 'https://api.pearktrue.cn/api/aichat/',
					method: 'GET'
				});
				
				if (response.data && response.data.models) {
					// 将API返回的模型转换为标准格式
					const apiModels = response.data.models.map(model => ({
						key: model,
						name: this.getModelDisplayName(model),
						description: this.getModelDescription(model)
					}));
					
					// 将API返回的模型添加到列表中
					// 如果API返回的模型与默认模型key相同，使用API返回的模型
					const modelKeys = new Set(defaultModels.map(m => m.key));
					apiModels.forEach(apiModel => {
						if (!modelKeys.has(apiModel.key)) {
							this.availableApis.push(apiModel);
						}
					});
				}
			} catch (error) {
				console.error('获取模型列表失败:', error);
			// 如果API请求失败，已经有默认模型列表，无需额外处理
		}
		
		// 设置默认选中的模型
		if (this.availableApis.length > 0) {
			this.currentApi = this.availableApis[0].key;
			this.currentApiName = this.availableApis[0].name;
		}
		
		// 加载历史消息
		this.loadHistory();
		// 加载设置
		this.loadSettings();
	},
	onUnload() {
		this.saveHistory()
		this.saveSettings()
		// 添加安全检查，确保方法存在再调用
		if (aiService && typeof aiService.clearContext === 'function') {
			aiService.clearContext()
		}
	},
	watch: {
		messages: {
			handler() {
				// 检查是否有新消息添加，如果有则滚动到底部
				// 强制滚动到底部，保证消息显示
				this.$nextTick(() => {
					this.scrollTop = 100000;
				});
			},
			deep: true
		}
	},
	methods: {
		goBack() {
			uni.navigateBack()
		},
		async sendMessage() {
			if (!this.inputMessage.trim() || this.isAiTyping) return;
			
			const userInput = this.inputMessage.trim();
			
			// 添加用户消息
			const userMessage = {
				type: 'user',
				content: userInput,
				time: Date.now()
			};
			
			this.messages.push(userMessage);
			this.allMessages.push(userMessage);
			this.inputMessage = '';
			
			// 显示AI正在输入状态
			this.isAiTyping = true;
			
			// 强制滚动到底部，不受isScrollingUp影响
			this.scrollTop = 100000;
			// 再使用nextTick确保DOM更新后滚动到底部
			this.$nextTick(() => {
				// 再次设置scrollTop确保滚动生效
				this.scrollTop = 100000;
				// 重置滚动状态
				this.isScrollingUp = false;
			});
			
			try {
				// 准备API请求参数
				const requestData = {
					model: this.currentApi,
					messages: [{
							role: 'user',
						content: userInput
					}],
					stream: false,
					temperature: this.temperature,
					top_p: this.top_p
				};
				
				// 发送API请求
				const response = await uni.request({
					url: 'https://api.pearktrue.cn/api/aichat/',
					method: 'POST',
					data: requestData,
					header: {
						'content-type': 'application/json'
					}
				});
				
				if (response.data && response.data.content) {
					// 添加AI回复消息
					const aiMessage = {
						type: 'ai',
						content: response.data.content,
						time: Date.now(),
						liked: false
					};
					
					// 先延迟一下再添加AI消息，让打字动画显示一会儿
					setTimeout(() => {
						this.messages.push(aiMessage);
						this.allMessages.push(aiMessage);
						
						// 保存聊天记录
						this.saveHistory();
						
						// 关闭AI输入状态
						this.isAiTyping = false;
						
						// 强制滚动到底部，不受isScrollingUp影响
						this.scrollTop = 100000;
						// 再使用nextTick确保DOM更新后滚动到底部
						this.$nextTick(() => {
							// 再次设置scrollTop确保滚动生效
							this.scrollTop = 100000;
							// 重置滚动状态
							this.isScrollingUp = false;
						});
					}, 800); // 延迟800毫秒再显示消息
				} else {
					throw new Error('API响应格式错误');
				}
				
			} catch (error) {
				console.error('发送消息失败:', error);
				uni.showToast({
					title: '发送失败，请重试',
					icon: 'none'
				});
				// 发生错误时关闭AI输入状态
				this.isAiTyping = false;
				
				// 强制滚动到底部，确保错误情况下也能正确显示
				this.scrollTop = 100000;
				this.$nextTick(() => {
					this.scrollTop = 100000;
					this.isScrollingUp = false;
				});
			}
		},
		scrollToBottom() {
			const query = uni.createSelectorQuery().in(this);
			query.select('.message-list').boundingClientRect();
			query.selectViewport().scrollOffset();
			query.exec((res) => {
				if (res[0]) {
					uni.pageScrollTo({
						scrollTop: res[0].height + 100,
						duration: 300,
						selector: '.message-list'
					});
				}
			});
		},
		async onRefresh() {
			this.isRefreshing = true
			await this.loadHistory()
			this.isRefreshing = false
		},
		copyMessage(content) {
			uni.setClipboardData({
				data: content,
				success: () => {
					uni.showToast({
						title: '已复制',
						icon: 'success',
						duration: 1500
					})
				}
			})
		},
		likeMessage(index) {
			const msg = this.messages[index]
			if (msg.type === 'ai') {
				// 在messages中更新
				this.$set(this.messages[index], 'liked', !msg.liked)
				
				// 在allMessages中找到对应消息并更新
				const allMsgIndex = this.allMessages.findIndex(m => 
					m.type === msg.type && 
					m.content === msg.content && 
					m.time === msg.time
				)
				if (allMsgIndex !== -1) {
					this.$set(this.allMessages[allMsgIndex], 'liked', !msg.liked)
				}
				
				// 保存更新后的聊天记录
				this.saveHistory()
				
				// 显示提示
				uni.showToast({
					title: msg.liked ? '已收藏' : '已取消收藏',
					icon: 'none',
					duration: 1500
				})
			}
		},
		showMenu() {
			this.showMenuPopup = true
		},
		hideMenu() {
			this.showMenuPopup = false
		},
		clearChat() {
			uni.showModal({
				title: '提示',
				content: '确定要清空聊天记录吗？',
				success: (res) => {
					if (res.confirm) {
						this.messages = []
						this.allMessages = []
						this.hasMore = false
						this.saveHistory()
						if (aiService && typeof aiService.clearContext === 'function') {
							aiService.clearContext()
						}
						this.hideMenu()
					}
				}
			})
		},
		saveHistory() {
			try {
				uni.setStorageSync('chat_history', JSON.stringify(this.allMessages))
			} catch (error) {
				console.error('保存聊天记录失败:', error)
			}
		},
		loadHistory() {
			try {
				const history = uni.getStorageSync('chat_history')
				if (history) {
					this.allMessages = JSON.parse(history)
					// 从最后一页开始加载
					const startIndex = Math.max(0, this.allMessages.length - this.pageSize)
					this.messages = this.processMessagesWithTimestamp(
						this.allMessages.slice(startIndex)
					)
					this.hasMore = startIndex > 0
					
					// 确保加载完成后滚动到底部
					this.$nextTick(() => {
						this.scrollToBottom()
					})
				}
			} catch (error) {
				console.error('加载聊天记录失败:', error)
			}
		},
		startVoice() {
			// 实现语音输入
			this.recording = true
			// TODO: 调用语音识别API
		},
		stopVoice() {
			this.recording = false
			// TODO: 停止语音识别
		},
		toggleEmojiPicker(e) {
			if (e) {
				e.stopPropagation()
			}
			this.showEmojiPicker = !this.showEmojiPicker
		},
		closeEmojiPicker() {
			if (this.showEmojiPicker) {
				this.showEmojiPicker = false
			}
		},
		insertEmoji(emoji) {
			const textarea = this.$refs.chatInput;
			if (!textarea) return;
			
			// 在光标位置插入表情
			const text = this.inputMessage;
			const cursorPosition = text.length; // 默认在末尾插入
			
			this.inputMessage = text.slice(0, cursorPosition) + emoji + text.slice(cursorPosition);
			
			// 关闭表情选择器
			this.showEmojiPicker = false;
			
			// 使用nextTick确保DOM更新后再设置焦点
			this.$nextTick(() => {
				// 使用uni-app的方法获取焦点
				uni.createSelectorQuery()
					.in(this)
					.select('.message-input')
					.boundingClientRect()
					.exec(() => {
						// 延迟一点执行focus
						setTimeout(() => {
							if (textarea && typeof textarea.focus === 'function') {
								textarea.focus();
							}
						}, 100);
					});
			});
		},
		onInputFocus() {
			this.showEmojiPicker = false
		},
		onInputBlur() {
			// 可以添加其他失焦逻辑
		},
		showFavorites() {
			// 显示收藏消息列表
			this.hideMenu()
		},
		openSettings() {
			this.showSettings = true
			this.hideMenu()
			// 确保DOM更新后再触发过渡动画
			this.$nextTick(() => {
				// 已经通过CSS类添加了动画效果
			})
		},
		hideSettings() {
			// 使用过渡效果平滑关闭（对于uni-app，不使用DOM操作）
			setTimeout(() => {
				this.showSettings = false
			}, 300) // 与CSS过渡时间一致
		},
		toggleDarkMode(e) {
			this.isDarkMode = e.detail.value
			// 应用深色模式样式
		},
		changeFontSize(e) {
			this.fontSize = e.detail.value
			// 更新字体大小
		},
		toggleContext(e) {
			this.enableContext = e.detail.value
			if (!this.enableContext) {
				if (aiService && typeof aiService.clearContext === 'function') {
					aiService.clearContext()
				}
			}
		},
		toggleAutoReply(e) {
			this.autoReply = e.detail.value
		},
		loadSettings() {
			try {
				const settings = uni.getStorageSync('ai_chat_settings')
				if (settings) {
					const parsed = JSON.parse(settings)
					this.isDarkMode = parsed.isDarkMode
					this.fontSize = parsed.fontSize
					this.enableContext = parsed.enableContext
					this.autoReply = parsed.autoReply
				}
			} catch (e) {
				console.error('加载设置失败:', e)
			}
		},
		saveSettings() {
			try {
				const settings = {
					isDarkMode: this.isDarkMode,
					fontSize: this.fontSize,
					enableContext: this.enableContext,
					autoReply: this.autoReply
				}
				uni.setStorageSync('ai_chat_settings', JSON.stringify(settings))
			} catch (e) {
				console.error('保存设置失败:', e)
			}
		},
		formatTime(timestamp) {
			if (!timestamp) return ''
			const date = new Date(timestamp)
			const hours = date.getHours().toString().padStart(2, '0')
			const minutes = date.getMinutes().toString().padStart(2, '0')
			return `${hours}:${minutes}`
		},
		sendQuickAction(action) {
			this.inputMessage = action
			this.sendMessage()
		},
		showApiSelector() {
			this.showApiPopup = true
		},
		selectApi(apiKey) {
			this.currentApi = apiKey;
			const selectedApi = this.availableApis.find(api => api.key === apiKey);
			if (selectedApi) {
				this.currentApiName = selectedApi.name;
				
				// 添加系统消息提示API切换
			this.messages.push({
					type: 'system',
					content: `已切换至 ${this.currentApiName}`,
					time: Date.now()
				});
				
				// 更新stream参数
				this.stream = apiKey === 'pearktrue';
			}
			this.showApiPopup = false;
		},
		onScroll(e) {
			// 记录当前滚动位置及滚动方向
			const currentScrollTop = e.detail.scrollTop;
			this.isScrollingUp = currentScrollTop < this.lastScrollTop;
			this.lastScrollTop = currentScrollTop;
		},
		onScrollToUpper() {
			if (this.hasMore && !this.isLoading) {
				this.loadMoreMessages()
			}
		},
		async loadMoreMessages(isInit = false) {
			if (this.isLoading || (!this.hasMore && !isInit)) return
			
			this.isLoading = true
			
			try {
				// 记录当前滚动位置
				const currentScrollTop = this.scrollTop
				
				// 加载更多消息的逻辑
				const pageSize = this.pageSize
				const currentLength = this.messages.length
				const totalLength = this.allMessages.length
				
				// 计算要加载的消息范围
				let startIndex = Math.max(0, totalLength - currentLength - pageSize)
				let endIndex = totalLength - currentLength
				
				if (startIndex >= endIndex) {
					this.hasMore = false
					this.isLoading = false
					return
				}
				
				// 获取新消息
				const newMessages = this.allMessages.slice(startIndex, endIndex)
				
				// 添加时间分割线
				const processedMessages = this.processMessagesWithTimestamp(newMessages)
				
				// 在现有消息前面添加新消息
				this.messages = [...processedMessages, ...this.messages]
				
				// 更新是否还有更多消息
				this.hasMore = startIndex > 0
				
				// 恢复滚动位置
				this.$nextTick(() => {
					this.scrollTop = currentScrollTop + 100 // 补偿新加载的消息高度
				})
			} finally {
				this.isLoading = false
			}
		},
		processMessagesWithTimestamp(messages) {
			if (!messages.length) return []
			
			const processed = []
			let lastTimestamp = 0
			
			messages.forEach(msg => {
				const currentTimestamp = msg.time
				
				// 如果与上一条消息时间间隔超过15分钟，添加时间分割线
				if (currentTimestamp - lastTimestamp > 15 * 60 * 1000) {
					processed.push({
						type: 'timestamp',
						time: currentTimestamp
					})
				}
				
				processed.push(msg)
				lastTimestamp = currentTimestamp
			})
			
			return processed
		},
		showMessageActions(msg, index) {
			if (msg.type === 'ai') {
				uni.showActionSheet({
					itemList: ['复制', msg.liked ? '取消收藏' : '收藏'],
					success: (res) => {
						switch (res.tapIndex) {
							case 0:
								this.copyMessage(msg.content)
								break
							case 1:
								this.likeMessage(index)
								break
						}
					}
				})
			}
		},
		async getRandomImage() {
			try {
				uni.showLoading({
					title: '获取图片中...'
				})
				
				const imageUrl = await imageService.getRandomImage()
				
				// 添加图片消息
				const imageMessage = {
					type: 'user',
					content: '[图片]',
					time: Date.now(),
					image: imageUrl
				}
				
				this.messages.push(imageMessage)
				this.allMessages.push(imageMessage)
				
				// 保存聊天记录
				this.saveHistory()
				
				// 自动滚动到底部
				this.scrollToBottom()
				
			} catch (error) {
			uni.showToast({
					title: '获取图片失败',
					icon: 'none'
				})
			} finally {
				uni.hideLoading()
			}
		},
		uploadImage() {
			uni.chooseImage({
				count: 1, // 最多可以选择的图片张数
				sizeType: ['compressed'], // 可以指定是原图还是压缩图，默认二者都有
				sourceType: ['album', 'camera'], // 从相册选择或使用相机拍照
				success: res => {
					const tempFilePaths = res.tempFilePaths
					// 显示加载中提示
					uni.showLoading({
						title: '发送图片中...'
					})
					
					// 创建图片消息
					const imageMessage = {
						type: 'user',
						content: '[图片]',
						time: Date.now(),
						image: tempFilePaths[0]
					}
					
					// 添加图片消息
					this.messages.push(imageMessage)
					this.allMessages.push(imageMessage)
					
					// 保存聊天记录
					this.saveHistory()
					
					// 自动滚动到底部
					this.scrollToBottom()
					
					// 隐藏加载提示
					uni.hideLoading()
				}
			})
		},
		previewImage(url) {
			if (!url) return
			uni.previewImage({
				urls: [url],
				current: 0
			})
		},
		getModelDisplayName(modelKey) {
			const displayNames = {
				'deepseek-v3': 'DeepSeek V3',
				'deepseek-r1': 'DeepSeek R1',
				'qwq-32b': 'QWQ-32B',
				'qwq-32b-online': 'QWQ-32B在线版',
				'qwen-max': '通义千问Max',
				'qwen-plus': '通义千问Plus',
				'qwen-turbo': '通义千问Turbo'
			};
			return displayNames[modelKey] || modelKey;
		},
		getModelDescription(modelKey) {
			const descriptions = {
				'deepseek-v3': 'DeepSeek最新版本模型',
				'deepseek-r1': 'DeepSeek基础版本',
				'qwq-32b': '离线大语言模型',
				'qwq-32b-online': '在线大语言模型',
				'qwen-max': '通义千问最强性能版本',
				'qwen-plus': '通义千问增强版本',
				'qwen-turbo': '通义千问快速版本'
			};
			return descriptions[modelKey] || '大语言模型';
		},
		// 优化自动滚动逻辑，减少多次调用
		autoScrollToBottom() {
			// 只调用一次滚动，避免频繁滚动导致跳动
			this.scrollToBottom(true);
		}
	}
}
</script>

<style lang="scss">
.container {
	height: 100vh;
	display: flex;
	flex-direction: column;
	background-color: var(--bg-color, #f5f5f5);
	
	&.dark-mode {
		--bg-color: #1a1a1a;
		--text-color: #fff;
		--bubble-bg: #2d2d2d;
		--bubble-text: #fff;
		--action-bg: #3d3d3d;
		--border-color: #404040;
	}
	
	.status-bar {
		flex: none;
		height: 20rpx;
		background-color: var(--bg-color, #f5f5f5);
	}
	
.nav-bar {
		flex: none;
		height: 88rpx;
	display: flex;
	align-items: center;
	justify-content: space-between;
	 padding: 10rpx 30rpx;
	 background-color: var(--nav-bg, #fff);
	 box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);

.back-btn, .action-btn {
	font-size: 40rpx;
	padding: 10rpx;
	color: var(--text-color, #333);
}

.nav-title {
			font-size: 32rpx;
			font-weight: bold;
			color: var(--text-color, #333);
		}
	}
	
.message-list {
		position: relative;
		overflow: hidden;
		background: #f8f9fa;
		transition: opacity 0.3s ease;
		opacity: 1;
		
		.loading-more {
			text-align: center;
			padding: 20rpx 0;
			color: #999;
			font-size: 24rpx;
}

.messages-container {
			height: 100%;
			padding: 20rpx;
			box-sizing: border-box;
			
.welcome-message {
				text-align: center;
				padding: 40rpx 0;

.welcome-header {
 display: flex;
	align-items: center;
					justify-content: center;
 margin-bottom: 20rpx;

.assistant-avatar {
 width: 80rpx;
 height: 80rpx;
						border-radius: 12rpx;
 margin-right: 20rpx;
}

.welcome-title {
 font-size: 32rpx;
						font-weight: bold;
						color: var(--text-color, #333);
					}
}

.welcome-text {
 font-size: 28rpx;
 color: #666;
}

.quick-questions {
 margin-top: 20rpx;

.quick-questions-title {
 font-size: 28rpx;
						color: #999;
						margin-bottom: 10rpx;
}

.quick-question {
 display: inline-block;
						padding: 10rpx 20rpx;
						border: 1rpx solid #eee;
						border-radius: 8rpx;
						margin: 0 10rpx;
						cursor: pointer;
						
						&:active {
							background-color: #f5f5f5;
						}
					}
				}
			}
			
.message-item {
				margin-bottom: 20rpx;
				
				&:last-child {
					margin-bottom: 0;
				}
				
				.message-content {
					display: flex;
					align-items: flex-start;
					position: relative;
					margin-bottom: 24rpx;
					
					&.user {
						flex-direction: row-reverse;
						justify-content: flex-start;
						align-items: flex-start;
						
						.message-bubble {
							margin-right: 16rpx;
							background: #0091EA;
							color: #fff;
							box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.1);
							padding: 20rpx;
							min-width: 60rpx;
							border-radius: 20rpx;
							border-top-right-radius: 4rpx;
							max-width: 70%;
							order: 2; /* 将消息气泡放在第二位 */
							
							.message-text {
								color: #fff;
								line-height: 1.5;
								font-size: 28rpx;
								word-break: break-word;
							}
							
							.message-image {
								margin-top: 10rpx;
								width: 320rpx;
								border-radius: 10rpx;
								max-width: 100%;
							}
						}
						
						.message-avatar {
							width: 64rpx;
							height: 64rpx;
							border-radius: 32rpx;
							background: #E3F2FD;
							display: flex;
							align-items: center;
							justify-content: center;
							margin-right: 30rpx;
							overflow: hidden;
							order: 1; /* 将头像放在第一位 */
							
							image {
								width: 100%;
								height: 100%;
								border-radius: 50%;
							}
						}
					}
					
					&.ai {
						flex-direction: row;
						justify-content: flex-start;
						
						.message-bubble {
							margin-left: 16rpx;
							margin-right: 30rpx;
							background: #fff;
							box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.1);
							padding: 20rpx;
							min-width: 60rpx;
							border-radius: 20rpx;
							border-top-left-radius: 4rpx;
							max-width: 70%;
							
							.message-text {
								color: #333;
								line-height: 1.5;
								font-size: 28rpx;
								word-break: break-word;
							}
							
							.message-image {
								margin-top: 10rpx;
								width: 320rpx;
								border-radius: 10rpx;
								max-width: 100%;
							}
						}
						
						.message-avatar {
							width: 64rpx;
							height: 64rpx;
							border-radius: 32rpx;
							background: #fff;
							display: flex;
							align-items: center;
							justify-content: center;
							box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.1);
							margin-left: 30rpx;
							overflow: hidden;
							
							image {
								width: 100%;
								height: 100%;
								border-radius: 50%;
							}
						}
					}
				}
			}
		}
	}
	
.input-area {
		flex: none;
		height: auto;
		padding: 20rpx;
		background-color: var(--input-bg, #fff);
		border-top: 1rpx solid var(--border-color, #eee);
		position: relative;
		z-index: 10;
		display: flex;
		flex-direction: column;

		.input-wrapper {
			display: flex;
			align-items: center;
			background: #fff;
			border: 1rpx solid #E0E0E0;
			box-shadow: 0 -2rpx 12rpx rgba(0,0,0,0.04);
			border-radius: 40rpx;
			padding: 12rpx 16rpx;
			margin-bottom: 12rpx;

			.message-input {
				flex: 1;
				font-size: 28rpx;
				min-height: 40rpx;
				max-height: 160rpx;
				line-height: 40rpx;
				color: var(--text-color, #333);
				padding: 8rpx 12rpx;
				margin: 0;
				background: transparent;
				
				&:disabled {
					opacity: 0.6;
				}
			}
			
			.send-btn {
				margin-left: 16rpx;
				width: 60rpx;
				height: 60rpx;
				border-radius: 30rpx;
				background: linear-gradient(135deg, #0091EA 0%, #2979FF 100%);
				box-shadow: 0 2rpx 8rpx rgba(41,121,255,0.2);
				color: #fff;
				font-size: 24rpx;
				display: flex;
				align-items: center;
				justify-content: center;
				padding: 0;
				flex-shrink: 0;
				
				&:disabled {
					background: #E0E0E0;
					box-shadow: none;
				}
				
				&:active {
					transform: scale(0.95);
					box-shadow: 0 2rpx 8rpx rgba(41, 121, 255, 0.1);
				}
			}
		}
		
		.quick-actions {
			display: flex;
			align-items: center;
			justify-content: space-around;
			margin-top: 16rpx;
			background-color: #f5f5f5;
			border-radius: 40rpx;
			padding: 10rpx 20rpx;
			width: 220rpx;
			
			.action-btn {
				width: 60rpx;
				height: 60rpx;
				font-size: 28rpx;
				display: flex;
				align-items: center;
				justify-content: center;
				border-radius: 30rpx;
				
				.action-icon {
					font-size: 32rpx;
				}
				
				&:active {
					background: #e0e0e0;
				}
			}
		}
	}
	
.voice-recording {
 position: fixed;
		bottom: 0;
		left: 0;
		right: 0;
		height: 120rpx;
		background-color: rgba(0, 0, 0, 0.5);
 display: flex;
	align-items: center;
		justify-content: center;

.recording-waves {
			width: 100rpx;
			height: 100rpx;
 position: relative;

.wave {
 position: absolute;
				width: 20rpx;
				height: 100rpx;
				background-color: #fff;
				border-radius: 10rpx;
				animation: waveAnimation 1.5s ease-in-out infinite;
				
				&:nth-child(2) {
					animation-delay: 0.2s;
				}
				
				&:nth-child(3) {
					animation-delay: 0.4s;
				}
}

.wave-1 {
				animation-duration: 0.5s;
}

.wave-2 {
				animation-duration: 0.6s;
}

.wave-3 {
				animation-duration: 0.7s;
			}
}

.recording-text {
			color: #fff;
			font-size: 28rpx;
			margin-top: 20rpx;
		}
	}
	
	.emoji-picker {
		position: fixed;
		left: 0;
		right: 0;
		bottom: 0;
		top: 0;  /* 扩展到整个屏幕 */
		z-index: 100;
		
		.emoji-picker-mask {
			position: absolute;
			top: 0;
			left: 0;
			right: 0;
			bottom: 0;
			background: rgba(0, 0, 0, 0.5);
		}
		
		.emoji-picker-content {
			position: absolute;
			bottom: 0;
			left: 0;
			right: 0;
			background-color: #fff;
			border-radius: 20rpx 20rpx 0 0;
			box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.2);
			animation: slideUp 0.3s ease;
			max-height: 60vh;
			
			.emoji-picker-header {
				display: flex;
				justify-content: space-between;
				align-items: center;
				padding: 20rpx 30rpx;
				border-bottom: 1rpx solid #eee;
				
				.emoji-picker-title {
					font-size: 28rpx;
					font-weight: bold;
					color: var(--text-color, #333);
				}
				
				.emoji-picker-close {
					font-size: 40rpx;
					color: var(--text-color, #999);
					padding: 10rpx;
				}
			}
			
			.emoji-grid {
				height: 400rpx;
				padding: 20rpx;
				
				.emoji-group {
					margin-bottom: 30rpx;
					
					.group-title {
						font-size: 24rpx;
						color: var(--text-color, #999);
						margin-bottom: 10rpx;
						padding: 0 20rpx;
					}
					
					.emoji-list {
						display: flex;
						flex-wrap: wrap;
						
						.emoji-item {
							width: 12.5%;
							height: 80rpx;
							display: flex;
							align-items: center;
							justify-content: center;
							cursor: pointer;
							transition: all 0.2s ease;
							border-radius: 10rpx;
							
							&:active {
								transform: scale(0.9);
								background-color: var(--action-bg, rgba(0,0,0,0.05));
							}
							
							text {
								font-size: 36rpx;
							}
						}
					}
				}
			}
		}
	}
	
	.settings-backdrop {
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		bottom: 0;
		background-color: rgba(0, 0, 0, 0.5);
		z-index: 99;
	}
	
	.settings-panel {
		position: fixed;
		top: 0;
		right: 0;
		bottom: 0;
		width: 80%; /* 使用百分比宽度而不是固定rpx值 */
		max-width: 700rpx; /* 设置最大宽度 */
		background-color: var(--panel-bg, #fff);
		box-shadow: -2rpx 0 10rpx rgba(0, 0, 0, 0.1);
		z-index: 101;
		display: flex;
		flex-direction: column;
		transform: translateX(100%);
		transition: transform 0.3s ease;
		
		&.visible {
			transform: translateX(0);
		}
		
		.panel-header {
			display: flex;
			align-items: center;
			justify-content: space-between;
			padding: 30rpx;
			border-bottom: 2rpx solid var(--border-color, #f0f0f0);
			flex: none;

			.panel-title {
				font-size: 36rpx;
				font-weight: bold;
				color: var(--text-color, #333);
			}

			.close-btn {
				font-size: 40rpx;
				color: var(--text-color, #999);
				padding: 10rpx;
				width: 60rpx;
				height: 60rpx;
				display: flex;
				align-items: center;
				justify-content: center;
				border-radius: 50%;
				
				&:active {
					background-color: rgba(0, 0, 0, 0.05);
				}
			}
		}

		.panel-content {
			flex: 1;
			overflow-y: auto;
			padding: 30rpx;
			-webkit-overflow-scrolling: touch;
			
			.setting-group {
				margin-bottom: 40rpx;
				
				.group-title {
					font-size: 32rpx;
					color: var(--text-color, #666);
					margin-bottom: 20rpx;
					padding-left: 10rpx;
					border-left: 6rpx solid #0091EA;
				}
				
				.setting-item {
					display: flex;
					align-items: center;
					justify-content: space-between;
					padding: 24rpx 10rpx;
					border-bottom: 2rpx solid var(--border-color, #f0f0f0);
					
					text {
						font-size: 30rpx;
						color: var(--text-color, #333);
						flex: 0 0 auto; /* 不让文本伸缩 */
						margin-right: 20rpx; /* 确保文本和控件之间有间距 */
						white-space: nowrap; /* 防止文本换行 */
					}
					
					switch, slider {
						margin-left: auto; /* 将控件推到右侧 */
					}
				}
			}
		}
	}
	
	.theme-picker {
 position: fixed;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
		background-color: rgba(0, 0, 0, 0.5);
		z-index: 100;
		animation: fadeIn 0.3s ease;

		.theme-picker-mask {
 position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
			background: rgba(0, 0, 0, 0.4);
}

		.theme-picker-content {
 position: absolute;
			top: 100rpx;
			right: 30rpx;
			background-color: #fff;
			border-radius: 20rpx;
			box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.2);
			animation: slideIn 0.3s ease;
			
			.theme-picker-header {
				display: flex;
				align-items: center;
				justify-content: space-between;
				padding: 30rpx;
				border-bottom: 2rpx solid var(--border-color, #f0f0f0);
				
				.theme-picker-title {
					font-size: 32rpx;
					font-weight: bold;
					color: var(--text-color, #333);
				}
				
				.theme-picker-close {
					font-size: 40rpx;
					color: var(--text-color, #999);
 padding: 10rpx;
				}
			}
			
			.theme-picker-list {
				padding: 30rpx;
				
				.theme-picker-item {
					padding: 30rpx;
					text-align: center;
					font-size: 28rpx;
					color: #333;
					border-bottom: 2rpx solid #f5f5f5;
					
					&:last-child {
						border-bottom: none;
					}
					
					&:active {
						background-color: #f5f5f5;
					}
				}
			}
		}
	}
	
	.model-picker {
 position: fixed;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
		z-index: 999;

		.model-picker-mask {
 position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
			background: rgba(0, 0, 0, 0.4);
		}
		
		.model-picker-content {
			position: relative;
			z-index: 1000;
			margin: 20rpx;
			padding: 20rpx;
			background: #fff;
			border-radius: 20rpx;
			box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
			
			.model-picker-header {
				display: flex;
				align-items: center;
				justify-content: space-between;
				padding: 30rpx;
				border-bottom: 2rpx solid var(--border-color, #f0f0f0);

				.model-picker-title {
					font-size: 32rpx;
					font-weight: bold;
					color: var(--text-color, #333);
				}

				.model-picker-close {
					font-size: 40rpx;
					color: var(--text-color, #999);
					padding: 10rpx;
				}
			}
			
			.model-picker-scroll {
				height: calc(100% - 100rpx);
				padding: 30rpx;
				
				.model-picker-item {
					padding: 30rpx;
					font-size: 30rpx;
					border-bottom: 1rpx solid #eee;
					
					&:last-child {
						border-bottom: none;
					}
					
					&.model-active {
						color: #2196f3;
						font-weight: 500;
					}
				}
			}
		}
	}
	
	.typing-indicator {
		margin-bottom: 0;
	}

	.typing-bubble {
		background-color: #ffffff;
		border-radius: 20rpx;
		border-top-left-radius: 4rpx;
		padding: 16rpx 20rpx;
		box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.1);
		display: flex;
		align-items: center;
		margin-left: 16rpx;
		margin-right: 30rpx;
		min-width: 80rpx;
		max-width: 70%;
	}

	.typing-dot {
		width: 12rpx;
		height: 12rpx;
		background-color: #999;
		border-radius: 50%;
		margin: 0 6rpx;
		animation: bounce 1.5s infinite;
	}

	.typing-dot:nth-child(2) {
		animation-delay: 0.2s;
	}

	.typing-dot:nth-child(3) {
		animation-delay: 0.4s;
	}

	@keyframes bounce {
		0%, 60%, 100% { transform: translateY(0); }
		30% { transform: translateY(-10rpx); }
	}
}

@keyframes fadeIn {
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}

@keyframes slideUp {
	from {
		transform: translateY(100%);
	}
	to {
		transform: translateY(0);
	}
}

@keyframes slideLeft {
	from {
		transform: translateX(100%);
	}
	to {
		transform: translateX(0);
	}
}

@keyframes waveAnimation {
	0% {
		transform: scale(1);
	}
	50% {
		transform: scale(1.5);
	}
	100% {
		transform: scale(1);
	}
}

.time-divider {
	display: flex;
	align-items: center;
	justify-content: center;
	margin: 20rpx 0;
	
	.time-text {
		font-size: 24rpx;
		color: #999;
		background: rgba(0, 0, 0, 0.03);
		padding: 4rpx 16rpx;
		border-radius: 12rpx;
	}
}

.system-message {
	text-align: center;
	padding: 8rpx 0;
	
	.system-text {
		display: inline-block;
		font-size: 24rpx;
		color: #999;
		background: rgba(0, 0, 0, 0.04);
		padding: 4rpx 12rpx;
		border-radius: 8rpx;
		line-height: 1.4;
	}
}

.slider-container {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	flex: 1; /* 占据剩余空间 */
	min-width: 240rpx; /* 最小宽度确保可以显示滑块 */
	max-width: 350rpx; /* 最大宽度限制 */
	
	.slider-value {
		font-size: 24rpx;
		color: #0091EA;
		margin-bottom: 8rpx;
		align-self: flex-end; /* 数值靠右对齐 */
	}
	
	.font-slider {
		width: 100%;
	}
}

.message-item {
	opacity: 0;
	animation: fadeIn 0.3s forwards;
}

@keyframes fadeIn {
	0% { opacity: 0; }
	100% { opacity: 1; }
}
</style> 